﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SmartDevice.Connectivity;
using WindowsPhone.Tools;

namespace EzDeploy_Console
{
    class Program
    {
        #region Vars
        static int _exitCode = 0;
        static bool isQuietInstal = false;
        static bool isUsingWpc = true;
        static private bool isOperating = false;
        static private Xap xap;
        static private bool IsWillStop = false;
        static private ObservableCollection<Xap> _xaps;
        static public ObservableCollection<Xap> Xaps
        {
            get
            {
                return _xaps;
            }
            private set
            {
                _xaps = value;
            }
        }

        static RemoteApplication existingInstall;

        static private string wpconnect_Path = @"WPConnect.exe";

        static private string _currentDeviceName;
        static private string CurrentDeviceName
        {
            set
            {
                if (value != null)
                {
                    if (value == "Windows Phone Device")
                    {
                        _currentDeviceName = "Phone";
                    }
                    if (value == "Windows Phone Emulator")
                    {
                        _currentDeviceName = "Emulator";
                    }
                }
            }
            get
            {
                return _currentDeviceName;
            }
        }

        static private RemoteApplicationEx _curSelectedInstalledApp;
        static public RemoteApplicationEx CurSelectedInstalledApp
        {
            get { return _curSelectedInstalledApp; }
            set
            {
                if (_curSelectedInstalledApp != value)
                {
                    _curSelectedInstalledApp = value;
                }
            }
        }

        static private WindowsPhoneDevice _device;
        static public WindowsPhoneDevice Device
        {
            get { return _device; }
            set
            {
                if (_device != value)
                {
                    _device = value;
                }
            }
        }

        #endregion
        static void Main(string[] args)
        {
            initial();
            
            //showMessage("================= EzDeploy_Console ===============");

            if (args.Length== 0)
            {
                WelCome();
            }
            else
            {
                RecieveArgs(args);
            }

            if (isQuietInstal)
            {
                Environment.Exit(_exitCode);
            }
            else
            {
                showMessage("Press any key to exit. Exit Code: " + _exitCode);
                Console.ReadKey();
                Environment.Exit(_exitCode);
            }
        }

        static void WelCome()
        {
            showMessage("Command:[/quiet] [/device:] [/wpcpath] [/nowpc]");
            showMessage("[/quiet]    <Args:none> <Description: Hide all console.writeline>");
            showMessage("[/device:]  <Args:[phone][emulator]> <Description:Choose target device> <Default: Phone>");
            showMessage("[/wpcpath:]  <Args:[string]> <Description:Define the file path of WPConnect.exe> <Default: [@\"WPConnect\"]>");
            showMessage("[/nowpc]  <Args:none Description:Don't use WPConnect.exe>");
        }

        static void RecieveArgs(string[] args)
        {
            if (args != null && args.Length > 0)
            {
                for (int i = 0; i < args.Length; i++)
                {
                    CommandOperation(args[i]);
                }
            }

            XapsOperation();
        }

        static void XapsOperation()
        {
            if (Xaps.Count != 0)
            {
                if (isQuietInstal)
                {
                    if (connect())
                    {
                        installXaps(Xaps);
                    }
                }
                else
                {
                    foreach (var item in Xaps)
                    {
                        showMessage("Added: " + item.FileName);
                    }
                    showMessage(">>>>Choose your operation<<<<");
                    showMessage("[1].Install\n[2].Unistall\n[3].Cancel");
                    switch (Console.ReadLine())
                    {
                        case "1":
                            if (connect())
                            {
                                installXaps(Xaps);
                            }
                            break;
                        case "2":
                            if (connect())
                            {
                                uninstallXaps(Xaps);
                            }
                            break;
                        case "3":
                            break;
                        default:
                            break;
                    }
                }
            } 
        }

        static void CommandOperation(string args)
        {
            string cmd = string.Empty;
            string cmd_content = string.Empty;
            if (args.Contains(":\\") && args.Contains(".xap"))
            {
                cmd = "/xap";
            }
            else if (args.Contains("/")&&args.Contains(":"))
            {
                string temp = args.Split(':')[0];
                cmd = temp;
                cmd_content = args.Split(':')[1];
            }
            else if (args.Contains("/"))
            {
                cmd = args;
            }
            switch (cmd)
            {
                case "/quiet":
                    //showMessage("开启安静模式");
                    isQuietInstal = true;
                    break;
                case "/device":
                    showMessage("目标设备:" + cmd_content);
                    showMessage(Device.SetCurrentDevice(cmd_content));
                    break;
                case "/xap":
                    sortInputFile(args);
                    break;
                case "/wpcpath":
                    wpconnect_Path = cmd_content;
                    showMessage("Save WPConnect.exe path : " + cmd_content);
                    break;
                case "/nowpc":
                    isUsingWpc=false;;
                    break;
                default:
                    showMessage("Unknow Command");
                    break;
            }
        }

        #region Xap & Device Operation

        static private void installxap()
        {
            if (_device.Connected)
            {
                if (isOperating == false)
                {
                    try
                    {
                        showMessage("Installing" + xap.Name);
                        isOperating = true;
                        _device.CurrentDevice.InstallApplication(xap.Guid, Guid.Empty, "genre", "noicon", xap.FilePath);
                        showMessage("Completed !");
                        isOperating = false;
                    }
                    catch (Exception ex)
                    {
                        showMessage("Error:" + ex.Message);
                    }
                }
                else
                {
                    showMessage("Please wait for the last operation to complete");
                }
            }
            else
            {
                showMessage("Instaltion failed:Device not connected");
            }
        }

        static private bool uninstallxap(Xap _xap)
        {
            if (_device.Connected)
            {
                if (isOperating == false)
                {
                    try
                    {
                        if (isXapExisted(_xap))
                        {
                            showMessage("Unistalling: " + _xap.FileName);
                            isOperating = true;
                            existingInstall = _device.CurrentDevice.GetApplication(_xap.Guid);
                            existingInstall.Uninstall();
                            _device.RefreshInstalledApps();
                            showMessage("Unistalled: "+_xap.FileName);
                            isOperating = false;
                            return true;
                        }
                        else
                        {
                            showMessage("Not Uninstalled: "+_xap.FileName);
                            return false;
                        }
                    }
                    catch (Exception ex)
                    {
                        showMessage("Not Uninstalled: " + _xap.FileName);
                        string msg = "Error:Unknown";
                        switch (ex.Message)
                        {
                            case "0x81030111":
                                msg = "Cause:" + CurrentDeviceName + " is using this app. Please try it later.";
                                break;
                            case "The device is not connect":
                                msg = "Cause:Device is not connected";
                                break;
                            default:
                                break;
                        }
                        showMessage(ex.Message + " " + msg);
                        return true;
                    }
                }
                else
                {
                    showMessage("Please wait for the last operation to complete");
                    return false;
                }
            }
            else
            {
                showMessage("Instaltion failed:Device not connected");
                return false;
            }

        }

        static private void updatexap()
        {
            if (_device.Connected)
            {
                if (isOperating == false)
                {
                    try
                    {
                        isOperating = true;
                        showMessage("Updatting ");
                        existingInstall = _device.CurrentDevice.GetApplication(xap.Guid);
                        existingInstall.UpdateApplication("genre", "noicon", xap.FilePath);
                        showMessage("Updated Successfully!");
                        isOperating = false;
                    }
                    catch (Exception ex)
                    {
                        showMessage(ex.Message.ToString());
                    }
                }
                else
                {
                    showMessage("Please wait for the last operation to complete");
                }
            }
            else
            {
                showMessage("Instaltion failed:Device not connected");
            }
        }

        static private bool smartinstallxap(Xap _xap)
        {
            if (_device.Connected)
            {
                try
                {
                    if (isXapExisted(_xap))
                    {
                        showMessage("Updatting: " + _xap.FileName);
                        isOperating = true;
                        existingInstall = _device.CurrentDevice.GetApplication(_xap.Guid);
                        existingInstall.UpdateApplication("genre", "noicon", _xap.FilePath);
                        showMessage("Updated: "+_xap.FileName);
                    }
                    else
                    {
                        showMessage("Installing: " + _xap.FileName);
                        isOperating = true;
                        _device.CurrentDevice.InstallApplication(_xap.Guid, Guid.Empty, "genre", "noicon", _xap.FilePath);
                        showMessage("Installed: " + _xap.FileName);
                    }
                    
                    _device.RefreshInstalledApps();
                    isOperating = false;
                    return true;
                }
                catch (Exception ex)
                {
                    showMessage("Not Installed: " + _xap.FileName);
                    string msg = "Error:Unknown";
                    switch (ex.Message)
                    {
                        case "0x81030111":
                            msg = "Cause:" + CurrentDeviceName + " is using this app. Please try it later.";
                            break;
                        case "The device is not connect":
                            msg = "Cause:Device is not connected";
                            break;
                        default:
                            break;
                    }
                    showMessage(ex.Message+" "+msg);
                    return false;
                }
            }
            else
            {
                showMessage("Instaltion failed:Device not connected");
                return false;
            }
        }

        static private void installXaps(ObservableCollection<Xap> _xaps)
        {
            showMessage("Begin installing these xap files");
            foreach (Xap item in _xaps)
            {
                if (!IsWillStop)
                {
                    smartinstallxap(item);
                }
                else
                {
                    showMessage("Operation is stopped");
                    break;
                }
            }
            IsWillStop = false;
        }

        static private void uninstallXaps(ObservableCollection<Xap> _xaps)
        {
            showMessage("Begin unistalling these xap files");
            foreach (Xap item in _xaps)
            {
                if (!IsWillStop)
                {
                    uninstallxap(item);
                }
                else
                {
                    showMessage("Operation is stopped");
                    break;
                }
            }
            IsWillStop = false;
        }

        static private void connectViaWpc()
        {
            isOperating = true;
            bool isWpconnectOk = false;
            if (wpconnect_Path == "")
            {
                showMessage("WPConnect.exe path is not defined，Please drop WPConnect.exe into these window");
            }
            else
            {
                if (IsZuneRunning()==false)
                {
                    showMessage("launching WPConnect...");
                    try
                    {
                        ProcessStartInfo procInfo = new ProcessStartInfo(wpconnect_Path);
                        procInfo.CreateNoWindow = true;
                        showMessage("Waiting for WPConnect to connect phone");
                        Process procBatch = Process.Start(procInfo);
                        while (!procBatch.HasExited)
                        {
                            ;
                        }
                        if (procBatch.ExitCode.ToString() == "0")
                        {
                            isWpconnectOk = true;
                            showMessage("WPConnect connected successfully !");
                        }
                        else
                        {
                            showMessage("WPConnect not connected !");
                        }
                    }
                    catch (Exception ex)
                    {
                        showMessage(ex.Message.ToString());
                        isOperating = false;
                    }
                }
                else
                {
                    showMessage("WPConnect won't launch");
                }
                isOperating = false;
            }

            if (isWpconnectOk && (IsZuneRunning() == false))
            {
                isOperating = true;
                showMessage("Connecting phone via WPConnect...");
                _device.Connect();
                showMessage(_device.StatusMessage);
            }
            isOperating = false;
        }

        static private bool connect()
        {
            isOperating = true;
            showMessage("Connecting " + CurrentDeviceName + "...");
            _device.Connect();
            showMessage(_device.StatusMessage);
            if (!_device.Connected)
            {
                showMessage("Failed in connecting" + CurrentDeviceName);
                if (isUsingWpc)
                {
                    connectViaWpc();
                }
            }
            isOperating = false;
            if (!_device.Connected)
            {
                _exitCode = 1;
                return false;
            }
            else
            {
                return true;
            }
        }

        static private bool isXapExisted(Xap xap)
        {
            if (_device.CurrentDevice.IsApplicationInstalled(xap.Guid))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion

        #region Other

        static private void initial()
        {
                Device = new WindowsPhoneDevice();
                Xaps = new ObservableCollection<Xap>();

                _device.Connected = false;
        }

        static private void sortInputFile(string filepath)
        {
            string fileExt = FileOpration.GetFileExtFromPath(filepath);

            if (fileExt.ToLower() == "xap")
            {
                getXapInfo(filepath);
            }
        }

        static private void showMessage(string msg)
        {
            if (!isQuietInstal)
            {
                Console.WriteLine(msg);
            }
        }

        static private bool IsZuneRunning()
        {
            foreach (Process singleProc in Process.GetProcesses())
            {
                if (singleProc.ProcessName.ToLower() == "zune")
                {
                    showMessage("Zune is running");
                    break;
                    
                }
                else
                {
                    return false;
                }
            }
            return true;
        }

        static private void addXapIfNotExisted(Xap _xap)
        {
            int temp = 0;
            try
            {
                foreach (Xap item in Xaps)
                {
                    if (item.FilePath == _xap.FilePath)
                    {
                        //showMessage("Not Added: "+xap.FileName);
                        temp++;
                        break;
                    }
                }
                if (temp == 0)
                {
                    Xaps.Add(_xap);
                    //showMessage("Added: "+xap.FileName);
                }
            }
            catch (Exception ex)
            {
                showMessage(ex.Message);
            }

        }

        static private void getXapInfo(string filepath)
        {
            xap = new Xap(filepath.Trim());
            addXapIfNotExisted(xap);
        }

        #endregion

    }
}
